package model;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;

import org.mybeans.dao.DAOException;
import org.mybeans.factory.BeanFactory;
import org.mybeans.factory.BeanFactoryException;
import org.mybeans.factory.BeanTable;
import org.mybeans.factory.DuplicateKeyException;
import org.mybeans.factory.MatchArg;
import org.mybeans.factory.RollbackException;
import org.mybeans.factory.Transaction;


/*
 * 
 * made by alesmana@andrew.cmu.edu

 */

public class TransactionDAO {
    private BeanFactory<databeans.Transaction> factory;

    
    public TransactionDAO() throws DAOException {
        try {
            // Get a BeanTable so we can create the "employee" table
            BeanTable<databeans.Transaction> transactionTable = BeanTable.getInstance(databeans.Transaction.class, "cfa_transaction");

            if (!transactionTable.exists()) {
                transactionTable.create("transactionID"); //Employee's username will be the PK for the table

                transactionTable.setIdleConnectionCleanup(true); //see below explanation
                // Get a BeanFactory which the actions will use to read and
                // write rows of the "user" table
                factory = transactionTable.getFactory();
                
                //initially populate with sample data
                bootData();
            } else {
                // Long running web apps need to clean up idle database connections.
                // So we can tell each BeanTable to clean them up. (You would only notice
                // a problem after leaving your web app running for several hours.)
                transactionTable.setIdleConnectionCleanup(true);

                // Get a BeanFactory which the actions will use to read and
                // write rows of the "user" table
                factory = transactionTable.getFactory();
            }

        } catch (BeanFactoryException e) {
            throw new DAOException(e);
        }
    }
   

    private void bootData() throws DAOException {
        databeans.Transaction transactionTest = new databeans.Transaction();
        
       //transactionTest.setTransactionID(1);
        try{
        
         Calendar cal = Calendar.getInstance();
         Date d2 = cal.getTime();
         
         cal.add(Calendar.DATE, -1); 
         Date d1=cal.getTime(); 
         
        // ********* buy order (Committed) **********    
        transactionTest = new databeans.Transaction();
        transactionTest.setSubmissionDate(d1);
        transactionTest.setExecuteDate(d1);     
        transactionTest.setCustomerID(1);
        transactionTest.setFundID(1);
        transactionTest.setSuccess(true);
        transactionTest.setAmount(25050);
        transactionTest.setShares(1234);
        transactionTest.setTransactionType(databeans.Transaction.BUY_ORDER);
        transactionTest.setCorrespondingTransactionID(0);

        create(transactionTest);

        // ********* sell order (Pending)**********
        transactionTest = new databeans.Transaction();
        transactionTest.setSubmissionDate(d1);
        transactionTest.setExecuteDate(d1); 
        transactionTest.setCustomerID(1);
        transactionTest.setFundID(1);
        transactionTest.setSuccess(true);
        transactionTest.setAmount(123432);
        transactionTest.setShares(55000);
        transactionTest.setTransactionType(databeans.Transaction.SELL_ORDER);
        transactionTest.setCorrespondingTransactionID(0);

        create(transactionTest);
        
        // ********* exchange sell order (Committed)**********
        transactionTest = new databeans.Transaction();
        transactionTest.setSubmissionDate(d1);
        transactionTest.setExecuteDate(d1);
        transactionTest.setCustomerID(1);
        transactionTest.setFundID(1);
        transactionTest.setSuccess(true);
        transactionTest.setAmount(123432);
        transactionTest.setShares(10500);
        transactionTest.setTransactionType(databeans.Transaction.EXCHANGE_SELL_ORDER);
        transactionTest.setCorrespondingTransactionID(4);

        create(transactionTest);

        // ********* exchange buy order(Pending) **********
       
        transactionTest = new databeans.Transaction();
        transactionTest.setSubmissionDate(d1);
        
        transactionTest.setExecuteDate(d1);
        transactionTest.setCustomerID(1);
        transactionTest.setCustomerID(1);
        transactionTest.setFundID(2);
        transactionTest.setSuccess(true);
        //transactionTest.setAmount(1234.3200866);
        //transactionTest.setShares(12.34567);
        transactionTest.setTransactionType(databeans.Transaction.EXCHANGE_BUY_ORDER);
        transactionTest.setCorrespondingTransactionID(3);
        create(transactionTest);

        // ********* Transaction(Committed) **********
        transactionTest = new databeans.Transaction();
        transactionTest.setSubmissionDate(d2);
        //transactionTest.setExecuteDate(d2); 
        transactionTest.setCustomerID(1);
        transactionTest.setFundID(1);
        transactionTest.setSuccess(false);
        transactionTest.setAmount(34250);
        //transactionTest.setShares(12.34567);
        transactionTest.setTransactionType(databeans.Transaction.BUY_ORDER);
        transactionTest.setCorrespondingTransactionID(0);

        create(transactionTest);

        // ********* sell order (Pending)**********
        transactionTest = new databeans.Transaction();
        transactionTest.setSubmissionDate(d2);
        //transactionTest.setExecuteDate(d);
        //transactionTest.setTransactionID(3);
        transactionTest.setCustomerID(1);
        transactionTest.setFundID(1);
        transactionTest.setSuccess(false);
        //transactionTest.setAmount(1234.3200866);
        transactionTest.setShares(238866);
        transactionTest.setTransactionType(databeans.Transaction.SELL_ORDER);
        transactionTest.setCorrespondingTransactionID(0);

        create(transactionTest);
        
        // ********* exchange sell order (Committed)**********
        transactionTest = new databeans.Transaction();
        transactionTest.setSubmissionDate(d2);
        //transactionTest.setExecuteDate(d1); 
        //transactionTest.setTransactionID(4);
        transactionTest.setCustomerID(1);
        transactionTest.setFundID(1);
        transactionTest.setSuccess(false);
        //transactionTest.setAmount(1234.3200866);
        transactionTest.setShares(2367);
        transactionTest.setTransactionType(databeans.Transaction.EXCHANGE_SELL_ORDER);
        transactionTest.setCorrespondingTransactionID(8);

        create(transactionTest);

        // ********* exchange buy order(Pending) **********
        transactionTest = new databeans.Transaction();
        transactionTest.setSubmissionDate(d2);
        //transactionTest.setTransactionID(5);
        transactionTest.setCustomerID(1);
        transactionTest.setFundID(2);
        transactionTest.setSuccess(false);
        //transactionTest.setAmount(34.3200866);
        //transactionTest.setShares(12.34567);
        transactionTest.setTransactionType(databeans.Transaction.EXCHANGE_BUY_ORDER);
        transactionTest.setCorrespondingTransactionID(7);

        create(transactionTest);

        }catch(Exception e){
        	System.out.println("TransactionDAO bootdate()+ "+e.getMessage()); 
        }

    }

    public databeans.Transaction create(databeans.Transaction trans) throws DAOException {
        databeans.Transaction dbTrans = null;
        try {
            Transaction.begin();
            dbTrans = factory.create(); //no need to input anything since the pk is generated automatically
            //newCustomer.setCustomerID(dbCustomer.getCustomerID());
            //System.out.println("transaction dbtrans has an id of .. " + dbTrans.getTransactionID());
            
            factory.copyInto(trans, dbTrans);
            Transaction.commit();
        } catch (DuplicateKeyException e) {
            throw new DAOException("A transaction with ID " + trans.getTransactionID() + " has already exists"); //a bit dumb... think of how to remove this
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
        
        return dbTrans;
        
    }

    public databeans.Transaction lookup(int id) throws DAOException {
        try {
            return factory.lookup(id);
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
    }

    protected BeanFactory<databeans.Transaction> getFactory() {
        return factory;
    }

    public databeans.Transaction[] getTransactions() throws DAOException {
        try {
            databeans.Transaction[] transactions = factory.match();
            Arrays.sort(transactions); // We want them sorted by last and first names (as per X.compareTo());
            return transactions;
        } catch (RollbackException e) {
            throw new DAOException(e);
        }
    }
    

    public void update(databeans.Transaction trans) throws DAOException {
        try {
            Transaction.begin();
            
            int id = trans.getTransactionID();

            databeans.Transaction dbTransaction = factory.lookup(id);
        
            if (dbTransaction == null) {
                throw new DAOException("Transaction does not exist transactionID= " + id );
            }
            
            //READ: assuming there can be no partial buy or sales
            dbTransaction.setExecuteDate(trans.getExecuteDate());
            dbTransaction.setAmount(trans.getAmount());
            System.out.println("ID"+id+"TransactionDAO shares:"+trans.getShares());
            dbTransaction.setShares(trans.getShares());
            dbTransaction.setSuccess(trans.isSuccess());
            dbTransaction.setCorrespondingTransactionID(trans.getCorrespondingTransactionID());
            
            Transaction.commit();
        } catch (RollbackException e) {
            throw new DAOException(e);
        } finally {
            if (Transaction.isActive())
                Transaction.rollback();
        }
    }
    
	public databeans.Transaction[] getUndoneTransactions() throws DAOException {
		try {       	
			databeans.Transaction[] list = factory.match(MatchArg.equals("executeDate",null));
			return list;
		} catch (Exception e) {
			throw new DAOException(e);
		}
	}
	
	public databeans.Transaction[] getPendingTransactions(int customerID) throws DAOException {
	       try {    
	    	   System.out.println("getPendingTransactions -> customer.id = " + customerID);
	            databeans.Transaction[] list = factory.match(MatchArg.equals("customerID",customerID), MatchArg.equals("executeDate", null));
	            return list;
	        } catch (RollbackException e) {
	        	System.out.println(e.getMessage());
	            throw new DAOException(e);
	        }
	}
    
    //added by Xiao Liang
	public databeans.Transaction[] getTransactions(int customerID) throws DAOException {
		try {
			System.out.println("getTransactions customer ID = " +  customerID);
			databeans.Transaction[] list = factory.match(MatchArg.equals("customerID",customerID));
			return list;
		} catch (RollbackException e) {
			System.out.println(e.getMessage());
			throw new DAOException(e);
		}
	}
	
	//added by Xiao Liang
	public Date getLastTradingDate(int customerID) throws DAOException {
		databeans.Transaction[] transactions = getTransactions(customerID);
		Date epoch = new Date(18000); //Jan 1, 1970, 00:00:00
		Date lastDate = epoch; 
		for (int i=0; i<transactions.length; i++){
			//only transactionType: buy and sell will be considered
			Date transactionDate = transactions[i].getExecuteDate();
			if((transactionDate!=null)&&(transactionDate.after(lastDate)))
					lastDate = transactionDate; 
		}
		System.out.println("TransactionDAO: "+lastDate.toString()); 
		return lastDate; 
	}
   
	public Date getLastSubmissionDate(int customerID) throws DAOException {
		databeans.Transaction[] transactions = getTransactions(customerID);
		Date epoch = new Date(18000); //Jan 1, 1970, 00:00:00
		Date lastDate = epoch; 
		for (int i=0; i<transactions.length; i++){
			//only transactionType: buy and sell will be considered
			Date submissionDate = transactions[i].getSubmissionDate();
			if((submissionDate!=null)&&(submissionDate.after(lastDate)))
					lastDate = submissionDate; 
		}
		System.out.println("TransactionDAO: "+lastDate.toString()); 
		return lastDate; 
	}

}
